【教程】STM32H743驱动RGB屏幕并移植LVGL v8.0 | 您所在的位置:网站首页 › stm32h750 ltdc频率 › 【教程】STM32H743驱动RGB屏幕并移植LVGL v8.0 |
硬件准备 正点原子H743开发板+7寸 RGB LCD显示屏 + SDRAM (注意RGB屏幕必须外扩显存) 软件准备STM32cubeMX 6.1.2 + Keil 5 创建cubeMX工程首先打开STM32cubeMX软件,选择 ACCESS TO MCU SELECTOR进入MCU 选择界面选中 STM32H743 然后开始项目 进入STM32cubeMX工程配置界面 首先切换选项卡到 Project Manager,我们注意到软件标题栏有个 Untitled * ,带星号表示当前进行过的操作未保存,按下ctrl + s 可以保存。我们每次操作完都尽量按下保存,防止cubeMX卡死导致没保存工程。 首先填写项目名称,已经项目保存路径,工具链IDE 我们选择为 MDK-ARM (keil 5)。修改堆区和栈区空间大小为0x2000。因为后面要移植lvgl,默认的堆区大小是不够的,栈区我们也放大一点。 然后给我圈起来的地方打个√,这样配置的外设都会单独生成c和h文件,不会都挤在main.c里面。 然后我们切换到引脚配置界面,按下ctrl+S保存项目,这样标题栏的星号就消失了。 配置SDRAM一般的MCU接口屏,比如SPI屏,8080接口屏,IIC接口屏是可以不需要外置显存的。这些屏幕可以通过发送命令当方式告诉屏幕坐标,然后再发送对应的像素值。但是RGB接口屏没命令可以发,一般是告诉LTDC一个内存地址,由LTDC控制器去内存拿像素值不断去扫描刷新屏幕的。所以要用到SDRAM或者SRAM。我们这里用到的是 W9825G6KH 这颗SDRAM,容量32MByte。我们的屏幕是1024 * 600的,颜色格式RGB 565 ,所以需要 1024*600*2 = 1,228,800 字节 = 1200 K字节 内存作为 屏幕显存。 SDRAM原理图 首先在最左侧栏目选中FMC,然后选择SDRAM1,配置如下。如果你用的不是上面的原理图,则需要根据具体硬件连接配置。 然后是下面部分时序的配置,这个是在 W9825G6KH 数据手册里的。 GPIO settings 不用管,如果你用的是正点原子H743核心板。直接点右上角生成工程,然后打开就可以了。 这里我们打开 fmc.c 文件,然后将SDRAM的初始化代码加入到 我圈到的位置。SDRAM芯片内部是有寄存器的,我们要通过fmc接口去发送命令配置这些寄存器然后才可以使用。 需要插入在/* USER CODE BEGIN 0 */注释行和 /* USER CODE END 0 */ 之间的代码如下 extern SDRAM_HandleTypeDef hsdram1; #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) uint8_t SDRAM_Send_Cmd(uint8_t bankx,uint8_t cmd,uint8_t refresh,uint16_t regval) { uint32_t target_bank=0; FMC_SDRAM_CommandTypeDef Command; if(bankx==0) target_bank=FMC_SDRAM_CMD_TARGET_BANK1; else if(bankx==1) target_bank=FMC_SDRAM_CMD_TARGET_BANK2; Command.CommandMode=cmd; Command.CommandTarget=target_bank; Command.AutoRefreshNumber=refresh; Command.ModeRegisterDefinition=regval; if(HAL_SDRAM_SendCommand(&hsdram1,&Command,0XFFFF)==HAL_OK) { return 0; } else return 1; } void SDRAM_Initialization_Sequence(void) { uint32_t temp=0; SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_CLK_ENABLE,1,0); HAL_Delay(1); SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_PALL,1,0); SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_AUTOREFRESH_MODE,8,0); temp=(uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | \ SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | \ SDRAM_MODEREG_CAS_LATENCY_2 | \ SDRAM_MODEREG_OPERATING_MODE_STANDARD | \ SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_LOAD_MODE,1,temp); HAL_SDRAM_ProgramRefreshRate(&hsdram1,677); }并在 MX_FMC_Init 中调用该初始化函数 编译并进入调试模式,我们在 main 中的while(1) 前面加个断点,运行到这里。然后在memory中访问 0XC0000000 地址,如果能看到一堆 FF ,就说明SDRAM 已经初始化成功了。如果是问号? 则说明初始化有问题,这样你就需要重新检查一下了。 然后我们提升下主频,这样就能更快的访问SDRAM了。只需要更改 1. 处的时钟到480Mhz 然后回车,然后其它三处红圈的频率会自动更改。由于我们配置了 SDRAM的频率是 HCLK /2 ,所以此时SDRAM的运行频率是 120Mhz。W9825G6KH -6 这款芯片最快是到166Mhz,懒得配置了。 重新点击右上方生成代码,如果我们没有关闭 MDK工程的话点击 Close就可以了。 切换会Keil 会提示 文件被外部修改,需要重新载入。我们全选 YES就可以了 重新下载程序,,然后进入仿真检查,SDRAM是否可以正确访问。此时SDRAM就算配置完毕。 RGB-LTDC配置接下来进入屏幕的配置。打开LTDC 然后选择RGB565模式,下面的配置如下 还需要配置层,一般我们用一层就可以了。层的帧缓存起始地址就是我们的SDRAM访问起始地址0XC0000000 接下来要配置GPIO, 这里需要改的引脚比较多。我们按照 LTDC_B LTDC_G LTDC_R的顺序修改。如果按照RGB的顺序修改你会发现有些引脚原本就被LTDC_B占了,如果你直接改cubeMX的 LTDC会自动关闭,再次打开你之前进行的操作就没了。(很坑) 需要改动的引脚如下 LTDC_B3 --> PG11 LTDC_B4 --> PI4 LTDC_B5 --> PI5 LTDC_B6 --> PI6 LTDC_B7 --> PI7 LTDC_G2 --> PH13 LTDC_G3 --> PH14 LTDC_G4 --> PH15 LTDC_G5 --> PI0 LTDC_G6 --> PI1 LTDC_R3 --> PH9 LTDC_R4 --> PH10 LTDC_R5 --> PH11 LTDC_R6 --> PH12直接搜索引脚,然后选中对应功能就算完事了。 然后把所有引脚的输出速度调到Hign,默认是 Low和very LOW。如果你用的默认引脚配置,那么你的屏幕速度只能到30Mhz,而且还闪烁。这款屏幕是可以到51.2Mhz的。 根据原理图,还有个屏幕背光引脚 PB5,我们设置为推挽输出,默认是高电平就可以了。 再调整下LTDC主频,到51.2Mhz。设置PLL3锁相环的DIVR3 除频器到 /5就可以了。 重新生成代码,然后打开KEIL5,编写屏幕测试代码 测试代码 #include static uint16_t LCD_BUFFER[600][1024] __attribute__((at(0XC0000000))); while(1){ memset(LCD_BUFFER,0xFF,sizeof(LCD_BUFFER)); HAL_Delay(1000); memset(LCD_BUFFER,0xAA,sizeof(LCD_BUFFER)); HAL_Delay(1000); memset(LCD_BUFFER,0xD0,sizeof(LCD_BUFFER)); HAL_Delay(1000); memset(LCD_BUFFER,0x00,sizeof(LCD_BUFFER)); HAL_Delay(1000); }声明一个 静态数组,并且固定到 0XC0000000 地址(SDRAM)。 下载代码并复位开发板应该可以看到屏幕在 白 --> 红 -->紫 -->黑 四种颜色进行切换。 至此屏幕的配置就算完成 LVGL 移植打开lvgl官网 https://github.com/lvgl/lvgl 下载lvgl源码,解压放到我们的项目文件夹中 进入lvgl-master文件夹,删除多余没用的文件,只剩下这些 修改lv_conf_template.h名称为 lv_conf.h 将examples文件夹内的porting文件夹复制到lvgl_cong.h 同级目录 进入porting文件夹修改lv_port_disp_template.h 和对应的c 文件名称 打开KEIL5 修改添加几个目录 LV_CORE LV_PORT LV_DEMO,分别存放lvgl源代码,lvgl移植文件,lvgl 演示程序 将src 路径下所有c文件添加到LVGL_CORE ,注意是 递归添加(大概几百个文件。。。) port里只添加 disp 的和 lv_conf.h 。这里我只演示移植显示,不移植触控 demo我们添加 demo/benchmark 下的文件,如果你想试试其它demo也可以都添加了 添加 lv-master 包含目录 在Define里添加个全局宏 LV_CONF_INCLUDE_SIMPLE 前面要有个英文逗号 打开lv_conf.h lv_port_disp.c lv_port_disp.h三个文件,开头有个if 0 ,把0 改成1,我画圈的地方要注意。还有lv_port_disp.h 在lv_port_disp.c中的名称 然后编译一遍会有1个错误和五百多个警告。警告不用管,我们解决下这个错误。 就是找不到包含的文件,改成我圈起来的。被注释掉的包含是之前的。 还有lv_port_disp.h中的包含也要改 再次编译还有3错误 打开lv_port_disp.c 注意两个画圈的地方。 修改这三个画圈的地方 找到这个函数,添加这行代码。 回到main.c 添加两个头文件的包含 找到滴答定时器的中断入口,添加这两行代码。 打开lvgl_conf.h LV_USE_DEMO_BENCHMARK 设置为1 ,才能用这个demo 再次回到 main 修改如下。其中第一个圈和第二个圈是固定的,以后就不要动了。中间的圈是启动演示程序,该程序会进行一个图形跑分测试。 编译然后下载程序,不出意外,会进行一个跑分程序 至此,所有移植就算完毕!!! 当然还可以通过 DMA2D 帮我们搬运像素。这样屏幕刷新会更快。 关于lvgl的学习请参考lvgl官方文档,这里只教大家搭建好学习环境。 |
今日新闻 |
推荐新闻 |
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 |